home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / batchut / rbsetnv1.zip / ENVFUNCS.C < prev    next >
Text File  |  1991-01-07  |  5KB  |  185 lines

  1. /*
  2.  * envfuncs.c - manipulate parent environment
  3.  *
  4.  * Author:        R. Brittain                        4/11/90
  5.  *
  6.  *                    This code placed in the public domain
  7.  *
  8.  */
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <dos.h>
  12. #include <stdlib.h>
  13. #include <io.h>
  14.  
  15. #define MEMCHECK(x)        if ((x) == NULL) fatal("Out of memory",1)
  16.  
  17. #ifdef UNIXCOMPAT
  18.  #define strupr(x)            (x)        /* disable upper-casing env-vars */
  19. #endif
  20.  
  21. /* prototypes */
  22.  
  23. int      get_env_index(char *var, char **env_var);
  24. int       getenvseg(unsigned *envseg);
  25. unsigned get_env_var(unsigned env_addr, char ***env_var, int *count);
  26. void      put_env_var(unsigned env_addr, unsigned seglen, char **env_var);
  27.  
  28. void      fatal(char *msg, int status);
  29.  
  30. extern unsigned _psp;
  31.  
  32. int get_env_index(char *var, char **env_var)
  33. {
  34. /*
  35.  * Find the index into the env_var array of the variable <var>.  If not
  36.  * found, returns the index of the terminating null entry
  37.  */
  38.     register int i;
  39.     char *temp;
  40.     MEMCHECK(temp = (char *)malloc(strlen(var)+2)) ;
  41.     strcpy( temp, var);
  42.     strupr(strcat(temp,"="));
  43.     for( i = 0; env_var[i]; i++ )    {
  44.         if(strstr(env_var[i], temp) == env_var[i]) break;
  45.     }
  46.     free(temp);
  47.     return(i);
  48. }
  49.  
  50.  
  51. int getenvseg(unsigned *envseg )
  52. {
  53. /*
  54.  * Try to locate the parent environment and fill in the segment address
  55.  * This routine has some OS version dependencies
  56.  * Returns     1  if environment found
  57.  *            0  if environment not found
  58.  */
  59.     unsigned    ppsp;
  60.     union REGS  regs;
  61.     int status ;
  62.  
  63.     regs.x.ax = 0xD44D;                        /* 4dos signature value */
  64.     regs.x.bx = 0;
  65.     int86(0x2F, ®s, ®s);                /* TSR multiplex interrput */
  66.     ppsp   = regs.x.cx;                        /* psp of immediate parent shell */
  67.  
  68.     if( regs.x.ax == 0x44dd && ppsp == *(unsigned far *)MK_FP(_psp,0x16) ) {
  69.         /*
  70.          * good, we are running 4dos - AND it is our parent
  71.          * in this case we don't care about dos version
  72.          */
  73.         *envseg =  *(unsigned far *)MK_FP(ppsp,0x2C);
  74.     } else {
  75.         /*
  76.          * Follow the pointers back to our parent psp and from there get the
  77.          * parent environment segment address
  78.          * With early command.com (pre 3.3) the lowest level shell did not fill
  79.          * in the environment segment (it is 0) but we can still find the
  80.          * environment since it always follows the lowest level shell directly
  81.          */
  82.         ppsp = *(unsigned far *)MK_FP(_psp,0x16);
  83.         *envseg =  *(unsigned far *)MK_FP(ppsp,0x2C);
  84.         if ((*envseg == 0) &&
  85.             (_osmajor <= 2 || (_osmajor == 3 && _osminor <= 20))) {
  86.             /*
  87.              * we have the pre 3.3 master command.com - have to assume that the
  88.              * environment segment directly follows the program segment
  89.              * so get the length from the MCB and add it to ppsp
  90.              */
  91.             *envseg = ppsp + *(unsigned far *)MK_FP(ppsp - 1, 3) + 1;
  92.         }
  93.     }
  94.     /*
  95.      * Verify that the owner of the envseg matches the ppsp we got above
  96.      * - just to be a little paranoid
  97.      */
  98.     if ( *(unsigned far *)MK_FP((*envseg)-1, 1) != ppsp) {
  99.         *envseg = 0 ;     /* something wrong :-( */
  100.         status  = 0;
  101.     } else {
  102.         status  = 1 ;
  103.     }
  104.     return(status);
  105. }
  106.  
  107.  
  108. unsigned get_env_var(unsigned env_addr, char ***env_var, int *count)
  109. {
  110. /*
  111.  * Copy the parent environment from the segment address given in env_addr, into
  112.  * the memory block pointed to by env_blk.
  113.  * Extract pointers to the start of each variable and build array env_var.
  114.  * Return the length of the environment block, (bytes, always a multiple of 16)
  115.  */
  116.     static char *env_blk;
  117.     unsigned i, len, offset;
  118.     unsigned seglen;
  119.  
  120.     seglen = *(unsigned far *)MK_FP(env_addr - 1, 3) * 16;
  121.     if ((env_blk = (char *)malloc(seglen)) == (char *)NULL)
  122.         fatal ("Cannot allocate memory for environment block", 5);
  123.  
  124.     movedata(env_addr, 0, _DS, (unsigned)&env_blk[0], seglen);
  125.     /*
  126.      * make one pass through, counting variables, and allocate space for the
  127.      * env_var array.  Allow for two extra entries - one to add a new variable
  128.      * and a terminating null.
  129.      */
  130.     i = 0;    offset = 0;
  131.     do    {
  132.         offset += strlen(env_blk+offset) + 1;
  133.         i++;
  134.     } while(*(env_blk+offset));
  135.     MEMCHECK (*env_var = (char **)malloc((i+2)*sizeof(char **))) ;
  136.     *count = i;
  137.  
  138.     /* load pointers to each of the strings in the array env_var[] */
  139.     i = 0;    offset = 0;
  140.     do    {
  141.         len = strlen(env_blk+offset);
  142.         (*env_var)[i] = env_blk+offset;
  143.         offset += len+1;
  144.         i++;
  145.     } while(*(env_blk+offset));
  146.     (*env_var)[i] = NULL;                /* terminate with an extra null */
  147.     return (seglen);
  148. }
  149.  
  150.  
  151. void put_env_var(unsigned env_addr, unsigned seglen, char **env_var)
  152. {
  153. /*
  154.  * Copy the modified environment from the allocated data area, using the
  155.  * env_var array of pointers, into the memory block pointed to by env_addr.
  156.  */
  157.     char    *var_addr;
  158.     unsigned offset, len, i;
  159.     unsigned zero = 0;
  160.     /*
  161.      * Cycle through once to test for environment overflow.  If overflow,
  162.      * nothing is copied to the old environment block
  163.      */
  164.     for( i=0, offset=0, len=0; env_var[i]; offset+=len, i++)    {
  165.         len = strlen(env_var[i]) + 1;
  166.         if (offset+len >= seglen-2)     /* overflow */
  167.             fatal ("Environment overflow - not modified\n",4);
  168.     }
  169.     /*
  170.      * Now actually copy the strings
  171.      */
  172.     for( i=0, offset=0, len=0; env_var[i]; offset+=len, i++)    {
  173.         len = strlen(env_var[i]) + 1;
  174.         if (len == 1) {
  175.             /* this entry was null - skip it */
  176.             len = 0;
  177.             continue;
  178.         }
  179.         var_addr = env_var[i];
  180.         movedata(_DS, (unsigned)var_addr, env_addr, offset, len);
  181.     }
  182.     /* stuff a zero word at the end of the environment block */
  183.     movedata(_DS, (unsigned)&zero, env_addr, offset, sizeof(unsigned));
  184. }
  185.